package cn.javaxc.mvcwork.framework.actions;
import cn.javaxc.mvcwork.controller.SecurityHook;
import cn.javaxc.mvcwork.framework.actions.*;
import cn.javaxc.mvcwork.framework.beans.TFormBean;
import cn.javaxc.mvcwork.control.web.Result;
import cn.javaxc.mvcwork.util.common.*;
import cn.javaxc.mvcwork.util.helper.*;
import java.util.*;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.*;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.ModelAndView;
import cn.javaxc.mvcwork.controller.MVCConfig;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;

public class SpringAction {

	@Autowired
	private MVCResults mvcresult;
	public final static String SystemError="SystemError";
	public final static String AJAXOBJECT="AjaxObject";
//	private XmlAttribute xmlconfig;
	protected TActionContext context;
//	protected String formBean;
//	protected String scopeKey;
	protected final Logger logger = Logger.getLogger(getClass());
	protected Map<String,String> results;
	public void setContext(TActionContext context){
		this.context=context;
	}
//	public void setScopeKey(String key) {
//		this.scopeKey = key;
//	}
//	public void setFormBean(String formBean){
//		this.formBean=formBean;
//	}
//	public void setResults(Map<String,String> results){
//		this.results=results;
//	}
  protected String getCommand() {
	HttpServletRequest request = context.getRequest();
	String command = "Index";
	String action = request.getServletPath();
	String[] ss=action.substring(1).split("/");
	if (ss.length>1){
		command=ss[1];
		if (command.endsWith(".do")){
			command=command.substring(0,command.length()-".do".length());
		}
	}
    return command;
  }
  private boolean isThrow(){
	  if (mvcresult!=null){
		Map<String,String> defaults=mvcresult.subset("defaults");
		if (defaults==null||defaults.get(SystemError)==null){
			return true;
		}
	  }
	  return false;
  }
  private Object invokeAction() throws Exception
  {    
	 Object   result=null;

	 String cmdstr=getCommand();
		long actionStartTime = System.currentTimeMillis();
		try{
//		context = new TActionContext(servlet,form,new cn.javaxc.mvcwork.framework.actions.Action(mapping.getPath().substring(1,mapping.getPath().length()),null), context.getRequest(), context.getResponse());

		result = ObjectHelper.invokeObjectEx(this,"execute" + cmdstr,new Object[0],new Class[0]);
		}catch(ClassNotFoundException e){
		  if (isThrow())throw e;
			context.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
	   } catch (NoSuchMethodException nm) {
		  if (isThrow())throw nm;
        logger.info("invokeAction.No Such Method Exception for method execute" + cmdstr + ". MESAGE = " + nm.getMessage());
		context.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND, "No Such Method Exception for method execute" + cmdstr);
      } catch (IllegalAccessException ia) {
		  if (isThrow())throw ia;
	        logger.info("invokeAction.Illegal Access Exception. MESSAGE = " + ia.getMessage());
	  } catch (java.lang.reflect.InvocationTargetException e) {
		  if (isThrow())throw e;
		  context.setError( e);
	      return (SystemError);
	  }
	  long actionExecuteTime = System.currentTimeMillis() - actionStartTime;
	  if (context.getRequest().getAttribute("__debug_action_time")!=null){
		context.getRequest().setAttribute("__debug_action_time", actionExecuteTime+(Long)context.getRequest().getAttribute("__debug_action_time"));
	  }else{
	      context.getRequest().setAttribute("__debug_action_time", actionExecuteTime);
	  }
      return result;

  }
    
  private String getActionPath(String s) {
    // For extension matching, we want to strip the extension (if any)
    int slash = s.lastIndexOf("/");
    int period = s.lastIndexOf(".");
    if ((period >= 0) && (slash >= 0) && (period > slash)) {
      return s.substring(slash + 1, period);
    }
    return s;
  }

    @RequestMapping({"/**"})
    public Object handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception{
//		if (SpringMVCAware.getDefault()!=null){
//			xmlconfig=SpringMVCAware.getDefault().getConfig().getActions().get(this.getClass().getName());		
//		}
//		String scopeKey=xmlconfig.getAttributes().get(MVCXml.ACTION.name.name());

//		ServletRequestAttributes attr=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
//		if (attr==null){
//			return null;
//		}
//		HttpServletRequest request = attr.getRequest();
//		HttpServletResponse response = attr.getResponse();
//		System.err.println(this.getClass().getName()+".request "+request);
		request.setAttribute("ctx","/myapi/");
		request.setAttribute("staticctx","/myapi/static/");
		String action = request.getServletPath();
		String[] ss=action.substring(1).split("/");
		action = ss[0];
		if(action.lastIndexOf(".")>0)action = action.substring(0,action.lastIndexOf("."));
		if (mvcresult!=null){
			results=mvcresult.subset("/"+action);
//			if (results==null){
//				throw new Exception(action);
//			}		
		}
		setContext(new TActionContext(SpringUtils.getBean(org.springframework.web.servlet.DispatcherServlet.class),null,this, request, response));
//		context.setPageContext(RequestUtil.forPageContext(context));
		this.context.setForward(new TActionForward());
		String res =verifySecurity();
		  if (res != null && res.length() > 0) {
			  if("-none-".equals(res))return null;
			return doLayout(res);
		  }
		request.setAttribute("__action__", this);
		Object form=null;
		if (results!=null&&results.get("scopeKey")!=null&&!results.get("scopeKey").isEmpty()){
			String scopeKey=results.get("scopeKey");
			if (true||request.getParameter("auto-populate") != null){
				if (request.getAttribute(scopeKey)!=null){
					form=request.getAttribute(scopeKey);
					context.setBean(form);
				}else{
					form=ObjectHelper.getBean(scopeKey);
					context.setBean(form);
					request.setAttribute("scopeKey", scopeKey);
					request.setAttribute(scopeKey, form);
					populateBean(form);

				}			
			}
			
		}
		if (getActionPath(request.getServletPath())!=null){
//			request.setAttribute("tjactionname", getActionPath(request));
		}
		try{
			String hasPerm=doPermission();
			if (hasPerm!=null){
				if("-none-".equals(hasPerm))return null;
				return doLayout(hasPerm);
			}			
		}catch(Exception e){
			context.setError( e);
			return doLayout(SystemError);
		}

		Object ret=invokeAction();
		if(ret==null||"-none-".equals(ret))return null;
		return doLayout(ret);
    }
	protected String doPermission() throws Exception{
		return null;
	}
	protected ModelAndView doLayout(Object ret) throws Exception{
		if (ret instanceof ModelAndView){
			return (ModelAndView)ret;
		}else if (ret!=null&&!(ret instanceof String )){
			RequestHelper.writeJson(context.getResponse(),ret);
			return null;
		}else if (AJAXOBJECT.equals(ret)){
			if (context.getAttribute("ajaxObject")==null){
				Result m=null;
				if (context.getActionError()!=null){
					m=Result.error(context.getActionError());
				}else if (context.getActionInfo()!=null){
					m=Result.ok(context.getActionError());
				}
				RequestHelper.writeJson(context.getResponse(),m);
			}else{
				RequestHelper.writeJson(context.getResponse(),context.getAttribute("ajaxObject"));
			}
			if(FrameHelper.getBaseSQL()!=null)FrameHelper.getBaseSQL().ajaxSql(context.getRequest());
			return null;
		}
		TActionForward forward=context.getForward();
//		if (SpringMVCAware.getDefault()!=null){
//			Map<String,String> result=xmlconfig.getParameter(ret,MVCXml.FORWARD.name.name());
//			if (result==null){
//				if (SpringMVCAware.getDefault().getConfig().getForwards().get(ret)!=null){
//					result=SpringMVCAware.getDefault().getConfig().getForwards().get(ret).getAttributes();
//				}
//			}
//			if (result!=null){
//				forward.setName(result.get(MVCXml.FORWARD.name.name()));
//				forward.setLayout(result.get(MVCXml.FORWARD.layout.name()));
//				forward.setPath(result.get(MVCXml.FORWARD.path.name()));
//				forward.setRedirect(Boolean.valueOf(result.get(MVCXml.FORWARD.redirect.name())));
//				if (result.get(MVCXml.FORWARD.layout.name())!=null){
//					context.setForward(doLayout());
//				}
//			}		
//		}else{
			if (results==null){
				return new ModelAndView(ret+"");
			}
			if (results.containsKey("results")){
				results=(Map)((Map)results).get("results");
			}
			String result=results.get(ret);
			if (result==null){
				Map<String,String> defaults=mvcresult.subset("defaults");
				result=defaults.get(ret);
				if (result!=null){
					results=defaults;
				}
			}
			if (result!=null){
				forward.setName((String)ret);
				forward.setLayout(results.get(ret+"."+"layout"));
				forward.setPath(result);
				if (results.get(ret+"."+"redirect")!=null){
					forward.setRedirect(Boolean.valueOf(((Map)results).get(ret+"."+"redirect").toString()));
				}
				if (forward.getLayout()!=null){
					context.setForward(doLayout());
				}
			}else if (SystemError.equals(ret)){
				if (context.getError()!=null){
					throw (Exception)context.getError();
				}
			}
//		}
		String path=context.getForward().getPath();
		if (forward.getRedirect()){
			path="redirect:"+path;
		}
		if (!forward.getRedirect()&&path.contains(".do")){
//			path=path.replace(".do","");
			RequestDispatcher dispatcher = context.getRequest().getRequestDispatcher(path);
			dispatcher.forward(context.getRequest(), context.getResponse());
			return null;
		}else{
			path=context.getConfig().get("layout.prefix","")+path;//context.getConfig().get("layout.suffix","");			
		}
		return new ModelAndView(path);
	}
	public String getTemplateLayout() {
		return "/"+context.getConfig().get("layout.htmlstyle","templates/template1");
	}
	protected TActionForward doLayout() {
		TActionForward mapforward=context.getForward();
		if (mapforward!=null){
			
			if (mapforward.getLayout()!=null&&mapforward.getLayout().length()>0){
				String templateForwardPath = mapforward.getPath();
				String forwardPath = getTemplateLayout()+"/"+mapforward.getLayout();
				context.getRequest().setAttribute("IncludeModule", templateForwardPath+ context.getConfig().get("layout.suffix",".jsp"));
				context.getRequest().setAttribute("IncludeTemplate", forwardPath+ context.getConfig().get("layout.suffix",".jsp"));
				TActionForward retforward= new TActionForward(); 
				retforward.setPath(forwardPath);
				return retforward;
			}
		}
		return mapforward;
	}

	protected String verifySecurity() throws Exception{
		return null;
	}
	protected void populateBean(Object bean){

	}
	public static HttpServletRequest getRequest() {

		ServletRequestAttributes attr=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
		if (attr!=null){
			return attr.getRequest();
		}
		return null;
	}
}
